#include <iostream>
#include <string>
#include <cstring>
#include <cerrno>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
#include "Task.hpp"
#include "thread_pool.hpp"

using namespace ns_threadpool;
using namespace ns_task;

void Usage(std::string proc)
{
    std::cout << "Usage: " << proc << " port" << std::endl;
}

// void ServiceIO(int new_sock)
// {
//         //提供服务,我们是一个死循环
//         while(true)
//         {
//             char buffer[1024];
//             memset(buffer, 0, sizeof(buffer));
//             ssize_t s = read(new_sock, buffer, sizeof(buffer)-1);
//             if(s > 0)
//             {
//                 buffer[s] = 0; //将获取的内容当成字符串
//                 std::cout << "client# " << buffer << std::endl;

//                 std::string echo_string = ">>>server<<<, ";
//                 echo_string += buffer;

//                 write(new_sock, echo_string.c_str(), echo_string.size());
//             }
//             else if(s == 0){
//                 std::cout << "client quit ..." << std::endl;
//                 break;
//             }
//             else {
//                 std::cerr << "read error" << std::endl;
//                 break;
//             }
//         }
// }

// void *HandlerRequest(void *args)
// {
//     pthread_detach(pthread_self());
//     int sock = *(int *)args;
//     delete (int*)args;

//     ServiceIO(sock);
//     close(sock);
// }

// ./tcp_server 8081
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
        return 1;
    }
    //tcp server
    //1. 创建套接字
    int listen_sock = socket(AF_INET, SOCK_STREAM, 0);
    if(listen_sock < 0) {
        std::cerr <<"socket error: " << errno << std::endl;
        return 2;
    }

    //2. bind
    struct sockaddr_in local;
    memset(&local, 0, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[1]));
    local.sin_addr.s_addr = INADDR_ANY;

    if(bind(listen_sock, (struct sockaddr*)&local, sizeof(local)) < 0)
    {
        std::cerr << "bind error: " << errno << std::endl;
        return 3;
    }


    //3. 因为tcp是面向连接的, a.在通信前，需要建连接 b. 然后才能通信
    //   一定有人主动建立(客户端，需要服务)，一定有人被动接受连接(服务器，提供服务)
    //   我们当前写的是一个server, 周而复始的不间断的等待客户到来
    //   我们要不断的给用户提供一个建立连接的功能
    //
    //   设置套接字是Listen状态, 本质是允许用户连接
    const int back_log = 5;
    if(listen(listen_sock, back_log) < 0){
        std::cerr << "listen error" << std::endl;
        return 4;
    }

    // signal(SIGCHLD, SIG_IGN); //在Linux中父进程忽略子进程的SIGCHLD信号，子进程会自动退出释放资源

    for( ; ; ) {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int new_sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
        if(new_sock < 0){
            continue;
        }
        uint16_t cli_port = ntohs(peer.sin_port);
        std::string cli_ip = inet_ntoa(peer.sin_addr);

        std::cout << "get a new link -> : [" << cli_ip << ":" << cli_port <<"]# " << new_sock << std::endl;
        //version 4：进程或者线程池
        //version2,3: a. 创建线程、进程无上限 b. 当客户链接来了，我们才给客户创建进程/线程
        //1. 构建一个任务
        Task t(new_sock);
        //2. 将任务push到后端的线程池即可
        ThreadPool<Task>::GetInstance()->PushTask(t);



        //version 3, 曾经被主线程打开的fd，新线程是否能看到，是否共享？
        // pthread_t tid;
        // int * pram = new int(new_sock);
        // pthread_create(&tid, nullptr, HandlerRequest, pram);
   
        // 3,4
        //version 2 版本-> 2.1
        // pid_t id = fork();
        // if(id < 0){
        //     continue;
        // }
        // else if( id == 0 ){ //曾经被父进程打开的fd，是否会被子进程继承呢? 无论父子进程中的哪一个，强烈建议关闭掉不需要的fd
        //     //child
        //     close(listen_sock);

        //     if(fork() > 0) exit(0); //退出的是子进程

        //     //向后走的进程，其实是孙子进程
        //     ServiceIO(new_sock);
        //     close(new_sock);
        //     exit(0);
        // }
        // else {
        //     //father,不需要等待
        //     //do nothing!
        //     waitpid(id, nullptr, 0); //这里等待的时候会不会被阻塞呢？ 不会
        //     close(new_sock);
        // }

        //version 1: 单进程版，没人使用!
        //ServiceIO(new_sock);
    }

    return 0;
}


